package com.ruoyi.manage.endpoint;


import com.alibaba.fastjson2.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 赵志冲
 */
@ServerEndpoint("/websocket/driver/{loginName}")
@Component
public class ChatWebSocketEndPoint {

    /**
     * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static final AtomicInteger onlineNum = new AtomicInteger(0);
    /**
     * concurrent包的线程安全Map，用来存放每个客户端对应的Session对象。
     */
    private static final Set<Session> connections = new CopyOnWriteArraySet<>();

    public static final Map<String, Session> userConnections = new ConcurrentHashMap<>();
    private String loginName;
    private Session session;

    private static RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate<Object, Object> redisTemplate) {
        ChatWebSocketEndPoint.redisTemplate = redisTemplate;
    }

    //处理四种事件
    //OnOpen  客户端发起连接 ，服务器端OnOpen响应
    //OnClose 客户端断开连接 ，服务器端OnCLose响应
    //OnMessage 客户端发送消息，服务器端OnMessage响应
    //OnError  客户端发生错误，服务器端OnError响应

    //关闭连接close()
    //发送消息send()

    @OnOpen
    public void onOpen(Session session, @PathParam("loginName") String loginName) {
        // 获取登录名
        this.loginName = loginName;
        this.session = session;
        connections.add(session);
        userConnections.put(loginName, session);
        onlineNum.incrementAndGet();
        String msg = String.format("欢迎 %s(%s)加入，当前在线人数 %d", loginName, session.toString(), onlineNum.get());
        System.out.println(msg);
        HashMap<String, Object> map = new HashMap<>();

        map.put("type", "ack");
        map.put("content", "听单成功");
        String s = JSON.toJSONString(map);
        session.getAsyncRemote().sendText(s);
    }

    // 处理连接关闭
    @OnClose
    public void onClose(Session session, @PathParam("loginName") String loginName) {
        connections.remove(session);
        onlineNum.decrementAndGet();
        userConnections.remove(loginName);
        String msg = String.format("%s(%s) 退出，当前在线人数 %d", loginName, session.toString(), onlineNum.get());
        System.out.println(msg);

        //broadcast(loginName+ " 退出聊天室");
    }

    /**
     * 接收到消息的监听方法
     * client write    ------>   server  read
     * server write    ------>   client  read
     *
     * @param message 自定义协议
     *                {//群聊
     *                "to":'all',
     *                "content":'hello'
     *                }
     *                {//私聊
     *                "to":'zhangsan',
     *                "content":'hello'
     *                }
     */
    @OnMessage
    public void onMessage(Session session, String message, @PathParam("loginName") String loginName) {
        String msg = String.format("发送者%s(%s)发送消息： %s", loginName, session.toString(), message);
        System.out.println(msg);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        System.out.println("onError");
        throwable.printStackTrace();
    }

    /**
     * 关闭
     *
     * @param session
     */
    public void close(Session session) {
        try {
            HashMap<String, Object> map = new HashMap<>();
            map.put("type", "ack");
            map.put("content", "听单取消");
            String s = JSON.toJSONString(map);
            session.getAsyncRemote().sendText(s);
            session.close();
            connections.remove(session);
            onlineNum.decrementAndGet();
            System.out.println("关闭连接");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 发送消息到某一个Session
     *
     * @param session
     * @param message
     */
    public static void send(Session session, String message) {
        session.getAsyncRemote().sendText(message);
    }

    /**
     * 广播消息
     *
     * @param msg
     */
    private void broadcast(String msg) {
        for (Session session : connections) {
            synchronized (session) {
                session.getAsyncRemote().sendText(msg);//发送消息
            }
        }
    }

}
